﻿/****************************************
Designed by WHD in LinAn.2023
字符串，内部保存的是const char*，
只支持UTF-8编码格式
****************************************/
#ifndef DSTRING_HPP
#define DSTRING_HPP

#include "../HDCore/DType.h"
#include "../HDCore/DGlobal.h"

class DStringIterator
{
public:
	DStringIterator(char* ptr = nullptr)
		: ptr_(ptr) {}

	DStringIterator(const DStringIterator& it)
		: ptr_(it.ptr_) {}

	DStringIterator& operator++()
	{
		++ptr_;
		return *this;
	}

	DStringIterator& operator++(int)
	{
		DStringIterator ret = *this;
		++*this;
		return ret;
	}

	DStringIterator& operator+=(DSizeType i)
	{
		ptr_ += i;
		return *this;
	}

	DStringIterator operator+(DSizeType i)
	{
		DStringIterator it = *this;
		it += i;
		return it;
	}

	DStringIterator& operator--()
	{
		--ptr_;
		return *this;
	}

	DStringIterator& operator--(int)
	{
		DStringIterator ret = *this;
		--*this;
		return ret;
	}

	DStringIterator& operator-=(DSizeType i)
	{
		ptr_ -= i;
		return *this;
	}

	DStringIterator operator-(DSizeType i)
	{
		DStringIterator it = *this;
		it -= i;
		return it;
	}

	char& operator*()
	{
		return *(ptr_);
	}

	char* operator->()
	{
		return ptr_;
	}

	DStringIterator& operator=(const DStringIterator& it)
	{
		ptr_ = it.ptr_;
		return *this;
	}

	bool operator==(const DStringIterator& it)
	{
		return ptr_ == it.ptr_;
	}

	bool operator!=(const DStringIterator& it)
	{
		return !(*this == it);
	}

private:
	char* ptr_;
};

class DString
{
	friend class DPrinter;
public:
	typedef DStringIterator iterator;

	DString(const char* str);
	DString(const DString& other);
	~DString();

	//static DString number();

	void adjustToSize();
	void append(char c) { pushBack(c); }
	void append(const DString& str) { pushBack(str); }
	char& at(DSizeType index) { return data_[index]; }
	const char& at(DSizeType index) const { return data_[index]; };
	iterator begin() { return iterator(data_); }
	void clear();
	iterator end() { return iterator(data_ + size_); }
	//T last() const;
	//T back() const { return last(); }
	//T first() const;
	//T front() const { return first(); }
	void pushBack(char c);
	void pushBack(const DString& str);
	
	//void pushFront(const T& data);
	//void insert(DSizeType index, const T& data);
	//T popBack();
	//T popFront();
	//void removeAt(DSizeType index);
	//void removeOne(const T& data);
	//void removeAll(const T& data);
	DSizeType size() const { return size_; }
	DSizeType length() const { return size(); }
	bool isEmpty() const { return 0 == size(); }
	char& operator[](DSizeType index) { return at(index); }
	const char& operator[](DSizeType index) const { return at(index); }
	DSizeType indexOf(const DString& data);
	//DList<DSizeType> indexListOf(const T& data);
	//int count(const T& data);

private:
	void refreshSize();
	void checkSpace(DSizeType needSize);

	char* data_;
	DSizeType size_;  // 不包括\0
	DSizeType space_;  // 包括\0
};

DString::DString(const char* str)
{
	if (str == nullptr)
	{
		data_ = new char('\0');
	}
	else
	{
		// DSizeType str_size = strlen(str);
		// data_ = new char[str_size+1];
		// for (DSizeType i = 0; i < str_size; ++i)
		// 	data_[i] = str[i];
		// data_[str_size] = '\0';
	}

	refreshSize();
}

DString::DString(const DString& other)
{
	DSizeType str_size = sizeof(other.data_) / sizeof(char);
	data_ = new char[str_size];
	for (DSizeType i = 0; i < str_size; ++i)
		data_[i] = other.data_[i];

	size_ = other.size_;
}

DString::~DString()
{
	delete[] data_;
}

void DString::adjustToSize()
{
	DSizeType charArrayLen = dCharArrayLen(data_);
	char* newData = new char[charArrayLen + 1];
	for (DSizeType i = 0; i < charArrayLen; ++i)
	{
		newData[i] = data_[i];
	}
	newData[charArrayLen] = '\0';
	space_ = charArrayLen + 1;
	delete[] data_;
	data_ = newData;
}

void DString::clear()
{
	data_ = new char('\0');
	size_ = 0;
}

void DString::pushBack(char c)
{
	checkSpace(size_ + 1);
	data_[size_] = c;
	++size_;
}

void DString::pushBack(const DString& str)
{
	checkSpace(size_ + str.size_);
	for (DSizeType i = 0; i < str.size_; ++i)
	{
		data_[size_ + i] = str.data_[i];
	}
	size_ += str.size_;
}

DSizeType DString::indexOf(const DString& data)
{
	return size();
}

void DString::refreshSize()
{
	size_ = 0;
	DSizeType i = 0;
	while (data_[i] != '\0')
	{
		if ((data_[i] & 0xE0) == 0xE0)  // 汉字
			i += 3;  // todo 容易跳过\0导致奔溃
		else  // 非汉字
			++i;

		++size_;
	}
}

void DString::checkSpace(DSizeType needSize)
{
	if (needSize + 1 > space_)
	{
		char* newData = new char[needSize * 2 + 1];
		DSizeType i = 0;
		while (data_[i] != '\0')
		{
			newData[i] = data_[i];
			++i;
		}
		newData[i] = '\0';
		space_ = needSize * 2 + 1;
	}
}

#endif  // DSTRING_HPP
